﻿using System.ComponentModel;
using System.Data;
using System.Data.Objects;
using System.Data.Objects.DataClasses;
using System.Diagnostics;
using System.Linq;
using RedRiver.Framework.XtraCommon.Extensions;
using RedRiver.Framework.XtraCommon.FormHelper;

namespace RedRiver.Framework.XtraCommon.Templates.Generic{
    public class EntityDetailEditForm : DetailEditForm{
        /// <summary>
        /// 必需的设计器变量。
        /// </summary>
        private IContainer components;

        public EntityDetailEditForm(){
            InitializeComponent();
        }

        public virtual IEntityDataContext DataContext{
            get;
            set;
        }

        protected override bool IsDataSourceChanged(System.Windows.Forms.BindingSource bindSource) {
            return DataContext.HasEntityChanged;
        }

        /// <summary>
        /// 初始化 数据上下文默认方法
        /// </summary>
        /// <typeparam name="TContext"></typeparam>
        /// <typeparam name="TModel"></typeparam>
        protected EntityDataContext<TContext> InitDataContext<TContext, TModel>()
            where TContext : ObjectContext, new()
            where TModel : EntityObject {
            return InitDataContext<TContext, TModel>(new TContext());
        }

        /// <summary>
        /// 初始化 数据上下文默认方法
        /// </summary>
        /// <typeparam name="TContext"></typeparam>
        /// <typeparam name="TModel"></typeparam>
        /// <param name="context"></param>
        protected EntityDataContext<TContext> InitDataContext<TContext, TModel>(TContext context)
            where TContext : ObjectContext
            where TModel : EntityObject {
            return InitDataContext<TContext, TModel>(new EntityDataContext<TContext>(context));
        }

        /// <summary>
        /// 初始化 数据上下文默认方法
        /// </summary>
        /// <typeparam name="TContext"></typeparam>
        /// <typeparam name="TModel"></typeparam>
        /// <param name="context"></param>
        protected EntityDataContext<TContext> InitDataContext<TContext, TModel>(EntityDataContext<TContext> context)
            where TContext : ObjectContext
            where TModel : EntityObject {
            DataContext = context;
            defaultBindingSource.DataSource = context.Context.GetObjectSet<TModel>().Where(t=>false);
            context.OnRefreshData = d => d.Refresh(RefreshMode.StoreWins, defaultBindingSource.Current);
            context.OnLoadData = d => d.Refresh(RefreshMode.ClientWins, defaultBindingSource);
            context.OnUpdateData = d =>{
                try{
                    d.SaveChanges();
                }catch(OptimisticConcurrencyException){
                    d.Refresh(RefreshMode.ClientWins,defaultBindingSource);
                    d.SaveChanges();
                }catch(UpdateException updateException){
                    Trace.WriteLine(updateException.ToString());
                    if(updateException.InnerException!=null){
                        Trace.WriteLine(updateException.InnerException);
                    }
                    throw;
                }
            };
            return context;
        }

        /// <summary>
        /// 清理所有正在使用的资源。
        /// </summary>
        /// <param name="disposing">如果应释放托管资源，为 true；否则为 false。</param>
        protected override void Dispose(bool disposing){
            if (disposing && (components != null)){
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        protected override void OnLoadData(){
            base.OnLoadData();
            if (DataContext != null){
                DataContext.LoadData();
            }
        }

        protected override void OnUpdateData(){
            base.OnUpdateData();
            if (DataContext != null){
                DataContext.UpdateData();
            }
        }

        public override void LoadData(object data) {
            if((DataContext!=null)&&(data is EntityObject)){
                var key = ((EntityObject) data).EntityKey;
                base.LoadData(DataContext.Context.GetObjectByKey(key));
            }else{
                base.LoadData(data);
            }
            RefreshState();
        }

        public override void OnRefreshData(){
            if (DataContext != null){
                DataContext.RefreshData();
            }
            RefreshState();
        }

        #region Windows 窗体设计器生成的代码

        /// <summary>
        /// 设计器支持所需的方法 - 不要
        /// 使用代码编辑器修改此方法的内容。
        /// </summary>
        private void InitializeComponent(){
            this.components = new System.ComponentModel.Container();
        }

        #endregion
    }
}